﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Configuration;
using System.Threading;
using System.Net;

namespace Agente
{
    class Agente
    {

        string Estado;
        int IdCliente = 0;
        int Recorrido = 0;
        Int32 ServerTcpPort;
        string ServerIP;
        int TiempoDeActualizacion;
        TcpListener Servidor;
        string IPLocal;
        IPAddress LocalAddress;
        Int32 Port;

        public Agente()
        {
            //Carga variables del config
            ServerTcpPort = Int32.Parse(ConfigurationManager.AppSettings["ServerTcpPort"]);
            ServerIP = ConfigurationManager.AppSettings["ServerIP"];
            TiempoDeActualizacion = Int32.Parse(ConfigurationManager.AppSettings["TiempoDeActualizacion"]);

            //Inicializa
            Estado = "00"; //Disponible

            //Comienza informe de estado
            Thread ThreadEstado = new Thread(InformarEstado);
            ThreadEstado.Start();

            Port = Int32.Parse(ConfigurationManager.AppSettings["TcpPort"]);
            IPLocal = ConfigurationManager.AppSettings["LocalIP"];
            LocalAddress = IPAddress.Parse(IPLocal);
        }

        private static TcpClient Connect(string ip, int port)
        {

            TcpClient AgenteVehiculo = null;

            try
            {
                // Create a TcpClient.
                AgenteVehiculo = new TcpClient(ip, port);
            }
            catch (ArgumentNullException e)
            {
                Console.WriteLine("ArgumentNullException: {0}", e);
            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e);
            }

            return AgenteVehiculo;
        }

        public bool Comenzar(int idCliente)
        {
            try
            {
                TcpClient AgenteVehiculo = Connect(ServerIP, ServerTcpPort);
                AgenteVehiculo.ReceiveTimeout = 20000;

                NetworkStream Stream = AgenteVehiculo.GetStream();
                string SMensaje = "02;" + idCliente + ";" + IPLocal + ";";
                byte[] BMensaje = System.Text.Encoding.ASCII.GetBytes(SMensaje);
                Stream.Write(BMensaje, 0, BMensaje.Length);

                byte[] BRespuesta = new Byte[256];
                Stream.Read(BRespuesta, 0, BRespuesta.Length);

                string SRespuesta = System.Text.Encoding.ASCII.GetString(BRespuesta);
                string[] ARespuesta = SRespuesta.Split(';');

                if (ARespuesta[0] == "OK")//Ack from server
                {
                    Estado = "01";
                    IdCliente = idCliente;
                    Thread newThread = new Thread(EsperarRespuesta);
                    newThread.Start();
                }
                else
                {
                    //tirar error
                }

                Stream.Close();
                AgenteVehiculo.Close();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public void Terminar()
        {
            Estado = "00";
           
        }

        private void ComenzarRecorrido()
        {
            Recorrido = 0;
            IdCliente = 0;
            while (Estado == "01")
            {
                Recorrido += 10;
                Thread.Sleep(10000);
            }
        }

        private void InformarEstado()
        {
            TcpClient EstadoVehiculo = Connect(ServerIP, ServerTcpPort);
            NetworkStream Stream = EstadoVehiculo.GetStream();

            while (true)
            {
                string SMensaje = "05;" + Estado + ";" + IdCliente + ";" + Recorrido + ";";
                byte[] BMensaje = System.Text.Encoding.ASCII.GetBytes(SMensaje);
                Stream.Write(BMensaje, 0, BMensaje.Length);

                byte[] BRespuesta = new Byte[256];
                Stream.Read(BRespuesta, 0, BRespuesta.Length);

                string SRespuesta = System.Text.Encoding.ASCII.GetString(BRespuesta);
                string[] ARespuesta = SRespuesta.Split(';');

                Thread.Sleep(TiempoDeActualizacion);
            }
        }

        private void EsperarRespuesta()
        {
            try
            {
                Servidor = new TcpListener(LocalAddress, Port);
                Servidor.Start();
                // Buffer para lectura
                Byte[] BDatos = new Byte[256];

                // Entra en el loop

                Console.Write("Esperando conexión. \n");

                TcpClient Cliente = Servidor.AcceptTcpClient();
                Console.WriteLine("Conectado.");

                while (true)
                {
                    // Crea Stream para lectura escritura
                    NetworkStream Stream = Cliente.GetStream();

                    //Espera datos
                    while (!Stream.DataAvailable) { }

                    int IDatos;

                    //Lee primer paquete de datos
                    IDatos = Stream.Read(BDatos, 0, BDatos.Length);

                    //Convierte a String
                    string SDatos = System.Text.Encoding.ASCII.GetString(BDatos);

                    //Obtener estado
                    string[] ARespuesta = SDatos.Split(';');

                    Estado = ARespuesta[0];

                    if (Estado == "01")
                    {
                        Thread ThreadRecorrido = new Thread(ComenzarRecorrido);
                        ThreadRecorrido.Start();
                    }
                    else if (Estado == "06")
                    {
                        //Avisar que no tiene saldo
                    }
                    else if (Estado == "07")
                    {
                        Terminar();
                    }
                }

            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e);
            }
            finally
            {
                // Stop listening for new clients.

            }
        }
    }
}
